package com.jx.mst.mst.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jx.mst.model.common.dtos.PageParams;
import com.jx.mst.model.common.dtos.ResponseResult;
import com.jx.mst.model.mst.dtos.MstInfoDtos;
import com.jx.mst.model.mst.dtos.MstInfoPageDtos;
import com.jx.mst.model.mst.reps.MstInfoReps;
import com.jx.mst.mst.dao.MstInfoDao;
import com.jx.mst.mst.entity.MstDetail;
import com.jx.mst.mst.entity.MstInfo;
import com.jx.mst.mst.entity.MstSel;
import com.jx.mst.mst.entity.dtos.MstInfoByIdDtos;
import com.jx.mst.mst.service.MstDetailService;
import com.jx.mst.mst.service.MstInfoService;
import com.jx.mst.mst.service.MstSelService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.jx.mst.model.common.redisCon.MseRedisCon.*;


/**
 * (MstInfo)表服务实现类
 *
 * @author makejava
 * @since 2023-12-26 14:02:56
 */
@Service("mstInfoService")
public class MstInfoServiceImpl extends ServiceImpl<MstInfoDao, MstInfo> implements MstInfoService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Resource
    private MstDetailService mstDetailService;
    @Resource
    @Lazy
    private MstSelService mstSelService;
    @Autowired
    RedissonClient redissonClient;

    @Override
    public ResponseResult addMstInfo(HttpServletRequest request,MstInfoDtos mstInfoDtos) {
        MstInfo mstInfo = BeanUtil.copyProperties(mstInfoDtos, MstInfo.class);
        mstInfo.setMstInfoCreatetime(new Date());
        String userId = request.getHeader("userId");
        if(StrUtil.isNotBlank(userId)){
            mstInfo.setMstInfoCreateuser(Long.valueOf(userId));
        }
        boolean save = save(mstInfo);
        MstDetail mstDetail = new MstDetail();
        mstDetail.setId(mstInfo.getId());
        mstDetail.setMstDetailInfo(mstInfoDtos.getMstDetail());
        mstDetailService.save(mstDetail);
        stringRedisTemplate.opsForZSet().add(REDIS_ZSET_MSTINFO,mstInfo.getId().toString() , 1);

        String count = stringRedisTemplate.opsForValue().get(REDIS_PREX_MSTSEL + mstInfoDtos.getMstSelId());
        int counts = Integer.valueOf(count) +1;
        stringRedisTemplate.opsForValue().set(REDIS_PREX_MSTSEL + mstInfoDtos.getMstSelId(),String.valueOf(counts));

        return ResponseResult.okResult("添加成功");
    }
    // 判断一个元素是否存在于ZSet中
    public boolean isMemberExists(String key, String member) {
        return stringRedisTemplate.opsForZSet().score(key, member) != null;
    }
    @Override
    public ResponseResult queryByPage(MstInfoPageDtos mstInfoPageDtos) {
        PageHelper.startPage(mstInfoPageDtos.getPageNum(), mstInfoPageDtos.getPageSize());
        List<MstInfo> list = query().like(StrUtil.isNotBlank(mstInfoPageDtos.getKey()), "mst_info_title", mstInfoPageDtos.getKey()).eq(StrUtil.isNotBlank(mstInfoPageDtos.getMstSelId()),"mst_sel_id", mstInfoPageDtos.getMstSelId()).orderByAsc("mst_info_sort").list();

//        List<MstInfoReps> collect = list.stream().map(item -> {
//            MstInfoReps mstInfoReps = BeanUtil.copyProperties(item, MstInfoReps.class);
//            boolean memberExists = isMemberExists(REDIS_ZSET_MSTINFO, item.getId().toString());
//            if (memberExists) {
////                Set<String> stringSet = stringRedisTemplate.opsForZSet().range(REDIS_ZSET_MSTINFO, 0, -1);
//                Double score = stringRedisTemplate.opsForZSet().score(REDIS_ZSET_MSTINFO, item.getId().toString());
//                mstInfoReps.setScore(score);
//            }else {
//                mstInfoReps.setScore(Double.valueOf(-1));
//            }
//            return mstInfoReps;
//
//        }).collect(Collectors.toList());
        PageInfo page = new PageInfo(list);
        return ResponseResult.okResult(page);
    }

    @Override
    public MstInfoByIdDtos getMstinfoById(String mstinfoId) {
        String cachedstr = stringRedisTemplate.opsForValue().get(REDIS_MSTINFO_CACHED_MSTINFO+mstinfoId);
        if(StrUtil.isNotBlank(cachedstr)){
            MstInfoByIdDtos bean = JSONUtil.toBean(cachedstr, MstInfoByIdDtos.class);
            return bean;
        }
        if(cachedstr!=null){
            return new MstInfoByIdDtos();
        }
        RLock lock = redissonClient.getLock(REDIS_MSTINFO_LOCK_MSTINFO);

        MstInfoByIdDtos mstInfoByIdDtos = new MstInfoByIdDtos();
        try {
            boolean flag = lock.tryLock(1, TimeUnit.MILLISECONDS);
            if(!flag){
                Thread.sleep(500);
                getMstinfoById(mstinfoId);
            }


            MstInfo mstInfo = getById(mstinfoId);
            mstInfoByIdDtos = BeanUtil.copyProperties(mstInfo, MstInfoByIdDtos.class);
            MstSel mstSel = mstSelService.getById(mstInfo.getMstSelId());
            mstInfoByIdDtos.setMstSel(mstSel);
            MstDetail mstDetail = mstDetailService.getById(mstinfoId);
            mstInfoByIdDtos.setMstDetail(mstDetail);
            List<MstInfo> mstInfoList = query().eq("mst_sel_id", mstInfo.getMstSelId()).orderByAsc("mst_info_sort").list().stream().limit(10).collect(Collectors.toList());
            mstInfoByIdDtos.setMstInfoList(mstInfoList);
            List<MstSel> mstSelList = mstSelService.query().orderByAsc("mst_sel_sort").list().stream().limit(10).collect(Collectors.toList());
            mstInfoByIdDtos.setMstSelList(mstSelList);
            JSONObject jsonObject = JSONUtil.parseObj(mstInfoByIdDtos);
            stringRedisTemplate.opsForValue().set(REDIS_MSTINFO_CACHED_MSTINFO+mstinfoId,jsonObject.toString(),30,TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
        return mstInfoByIdDtos;
    }
}

